package dd.lo.ml;

import dd.lo.HelloCV;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.TermCriteria;
import org.opencv.ml.Ml;
import org.opencv.ml.SVM;
import org.opencv.ml.TrainData;

/**
 * https://docs.opencv.org/4.x/d1/d73/tutorial_introduction_to_svm.html
 */
public class SvmExample1 {

    private static final String ROOT = HelloCV.class.getResource("/").getPath();

    static {
        System.load(ROOT + "libopencv_java481.dylib");
    }

    public static void main(String[] args) {
        System.out.printf("ROOT: %s\n", ROOT);
        // 初始化数据集（示例数据）
        Mat trainMat = new Mat(3, 2, CvType.CV_32FC1); // 假设有3个样本，每个样本有2个特征
        trainMat.put(0, 0, new float[]{5, 2, 4, 4, 15, 16});
        Mat labelMat = new Mat(3, 1, CvType.CV_32SC1); // 存储对应的3个标签
        labelMat.put(0, 0, new int[]{1, 1, 0});
        TrainData trainData = TrainData.create(trainMat, Ml.ROW_SAMPLE, labelMat);

        // 创建SVM对象并设置参数
        SVM svm = SVM.create();
        svm.setType(SVM.C_SVC); // 设置SVM类型为C_SVC（分类）
        svm.setKernel(SVM.LINEAR); // 设置核函数为线性核函数
        svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 100, 1e-6));
        svm.train(trainData);

        //保存SVM模型
        svm.save(ROOT + "svm_sample_1.xml");

        //读取SVM模型
        SVM predictor = SVM.load(ROOT + "svm_sample_1.xml");

        // 使用训练好的模型进行预测（测试）
        Mat testSample = new Mat(1, 2, CvType.CV_32FC1); // 创建一个测试样本
        testSample.put(0, 0, new float[]{2, 3}); // 设置测试样本特征值
        double result = predictor.predict(testSample); // 进行预测
        System.out.println("Predicted label: " + result); // 输出预测结果
        //多做几个预测
        testSample.put(0, 0, new float[]{1, 1});
        System.out.println("Predicted label: " + predictor.predict(testSample));
        testSample.put(0, 0, new float[]{13, 15});
        System.out.println("Predicted label: " + predictor.predict(testSample));
        testSample.put(0, 0, new float[]{8, 9});
        System.out.println("Predicted label: " + predictor.predict(testSample));
        testSample.put(0, 0, new float[]{10, 12});
        System.out.println("Predicted label: " + predictor.predict(testSample));
    }
}
